const { src, dest, parallel, series, watch } = require("gulp");

const del = require("del");
const browserSync = require("browser-sync"); //实现开发服务器，自动热更新

const loadPlugins = require("gulp-load-plugins"); //利用gulp-load-plugins自动加载插件

const plugins = loadPlugins();
const bs = browserSync.create(); //创建

const cwd = process.cwd();
let config = {
  build: {
    src: "src",
    dist: "dist",
    temp: "temp",
    public: "public",
    paths: {
      styles: "assets/styles/*.scss",
      scripts: "assets/scripts/*.js",
      pages: "*.html",
      images: "assets/images/**",
      fonts: "assets/fonts/**",
    },
  },
};
try {
  const loadConfig = require(`${cwd}/page.config.js`);
  config = Object.assign({}, config, loadConfig);
} catch (error) {}

const clean = () => {
  return del([config.build.dist, config.build.temp]); //del提供清除任务
};

//针对scss
const style = () => {
  return src(config.build.paths.styles, {
    base: config.build.src,
    cwd: config.build.src,
  }) //base指定转换的基准路径
    .pipe(plugins.sass({ outputStyle: "expanded" })) //scss会默认将带下划线开头的scss文件是依赖文件，不会被转换
    .pipe(dest(config.build.temp))
    .pipe(bs.reload({ stream: true })); //以流的方式往浏览器推
};

// 针对js
const script = () => {
  return src(config.build.paths.scripts, {
    base: config.build.src,
    cwd: config.build.src,
  })
    .pipe(plugins.babel({ presets: ["@babel/preset-env"] })) //安装babel之后需要单独安装他的依赖模块@babel/preset-env
    .pipe(dest(config.build.temp))
    .pipe(bs.reload({ stream: true }));
};

// html页面编译
const page = () => {
  return src(config.build.paths.pages, {
    base: config.build.src,
    cwd: config.build.src,
  }) //因为页面使用的swig,所以使用swig模板引擎插件
    .pipe(plugins.swig({ data: config.data, defaults: { cache: false } })) // 防止模板缓存导致页面不能及时更新
    .pipe(dest(config.build.temp))
    .pipe(bs.reload({ stream: true }));
};

//图片转换
const image = () => {
  return src(config.build.paths.styles, {
    base: config.build.src,
    cwd: config.build.src,
  })
    .pipe(plugins.imagemin()) //图片压缩
    .pipe(dest(config.build.dist));
};

//字体文件如果有svg,也可以用imagemin
const font = () => {
  return src(config.build.paths.fonts, {
    base: config.build.src,
    cwd: config.build.src,
  })
    .pipe(plugins.imagemin())
    .pipe(dest(config.build.dist));
};

//其他文件直接拷贝
const extra = () => {
  return src("**", {
    base: config.build.public,
    cwd: config.build.public,
  }).pipe(dest("dist"));
};

const serve = () => {
  watch(config.build.paths.styles, { cwd: config.build.src }, style); //利用watch监听目录下的某个文件去执行编译操作
  watch(config.build.paths.scripts, { cwd: config.build.src }, script);
  watch(config.build.paths.pages, { cwd: config.build.src }, page);
  // watch('src/assets/images/**', image)
  // watch('src/assets/fonts/**', font)
  // watch('public/**', extra)
  watch(
    [config.build.paths.images, config.build.paths.fonts, "public/**"],
    { cwd: config.build.src },
    bs.reload // 更新浏览器
  );
  watch("**", { cwd: config.build.public });
  //开发服务器配置
  bs.init({
    notify: false, //弹出提示
    port: 2080, //启动端口
    // open: false,
    // files: 'dist/**',
    server: {
      baseDir: [config.build.temp, config.build.src, config.build.public], //根目录，数组模式会按照下标依次去找
      routes: {
        "/node_modules": "node_modules", //重定义路由，主要是链接dist和node_modules
      },
    },
  });
};
/**
 * gulp常用插件之gulp-useref使用
 * 更多gulp常用插件使用请访问：gulp常用插件汇总
 * gulp-useref这是一款可以将HTML引用的多个CSS和JS合并起来，
 * 减小依赖的文件个数，从而减少浏览器发起的请求次数。
 * gulp-useref根据注释将HTML中需要合并压缩的区块找出来，
 * 对区块内的所有文件进行合并
 * 它只负责合并，不负责压缩！,如果需要做其他操作，可以配合gulp-if插件使用.
 */
const useref = () => {
  return (
    src(config.build.paths.pages, {
      base: config.build.temp,
      cwd: config.build.temp,
    })
      .pipe(plugins.useref({ searchPath: [config.build.temp, "."] }))
      // html js css 压缩
      .pipe(plugins.if(/\.js$/, plugins.uglify()))
      .pipe(plugins.if(/\.css$/, plugins.cleanCss()))
      .pipe(
        plugins.if(
          /\.html$/,
          plugins.htmlmin({
            collapseWhitespace: true,
            minifyCSS: true,
            minifyJS: true,
          })
        )
      )
      .pipe(dest(config.build.dist))
  );
};

const compile = parallel(style, script, page); //创建组合任务

// 上线之前执行的任务
const build = series(
  clean,
  parallel(series(compile, useref), image, font, extra)
);

const develop = series(compile, serve);

module.exports = {
  clean,
  build,
  develop,
};
